package com.example.demo.shiro;

import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.context.annotation.Lazy;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zhaiding
 * @since 2019/6/1
 */
@Slf4j
public class ShiroService {

    @Lazy
    @Resource
    private ShiroFilterFactoryBean shiroFilterFactoryBean;

    /**
     * 过滤规则
     * <p>
     * 统一返回 json
     */
    public Map<String, String> loadFilterChainDefinitions() {
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();

        filterChainDefinitionMap.put("/login", "anon");

        // path: url==method eg: http://api/menu==GET   需要解析出path中的url和 httpMethod
        // httpMethod 必须大写

        /*List<Menu> menuList = menuService.getLeafNodeMenu();
        for (Menu menu : menuList) {
            String url = menu.getUrl();
            if (url != null) {
                String perms = "perms[" + menu.getPerms() + "]";
                filterChainDefinitionMap.put(url, perms);
            }
        }*/
        // todo : 从数据库获取权限

        //除了以上的请求外，其它请求都需要登录
        filterChainDefinitionMap.put("/**", "perms");
        return filterChainDefinitionMap;
    }


    /**
     * 调用此方法进行动态刷新过滤链
     */
    public synchronized void updatePermission() {
        AbstractShiroFilter shiroFilter;
        try {
            shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean
                    .getObject();
        } catch (Exception e) {
            throw new RuntimeException(
                    "get ShiroFilter from ShiroFilterFactoryBean error !");
        }

        Assert.notNull(shiroFilter, "ShiroFilter is null !");
        // 获取过滤管理器
        PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter
                .getFilterChainResolver();
        DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver
                .getFilterChainManager();
        // 清空拦截管理器中的存储
        manager.getFilterChains().clear();
        shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();


        shiroFilterFactoryBean
                .setFilterChainDefinitionMap(loadFilterChainDefinitions());
        // 相当于新建的 map, 因为已经清空了
        Map<String, String> chains = shiroFilterFactoryBean
                .getFilterChainDefinitionMap();
        for (Map.Entry<String, String> entry : chains.entrySet()) {
            String url = entry.getKey().trim().replace(" ", "");
            String chainDefinition = entry.getValue().trim()
                    .replace(" ", "");
            manager.createChain(url, chainDefinition);
        }
        log.info("更新过滤链成功!");
    }

}
